1 + 2
3
ACTL3143 & ACTL5111 Deep Learning for Actuaries
A recording covering (most of) this Python content:
It is general purpose language
Python powers:
Python is on Mars.
…[T]he entire machine learning and data science industry has been dominated by these two approaches: deep learning and gradient boosted trees… Users of gradient boosted trees tend to use Scikit-learn, XGBoost, or LightGBM. Meanwhile, most practitioners of deep learning use Keras, often in combination with its parent framework TensorFlow. The common point of these tools is they’re all Python libraries: Python is by far the most widely used language for machine learning and data science.
In R you can run:
pchisq(3, 10)
In Python it is
from scipy import stats
10).cdf(3) stats.chi2(
1 + 2
3
= 1
x + 2.0 x
3.0
type(2.0)
float
type(1), type(x)
(int, int)
= 1 + 1 == 2
does_math_work print(does_math_work)
type(does_math_work)
True
bool
= 1 != 1
contradiction contradiction
False
If we want to add 2 to a variable x
:
= 1
x = x + 2
x x
3
= 1
x += 2
x x
3
Same for:
x -= 2
: take 2 from the current value of x
,x *= 2
: double the current value of x
,x /= 2
: halve the current value of x
.= "Patrick"
name = "Laub" surname
= "This is Patrick's coffee"
coffee = 'And then he said "I need a coffee!"' quote
+ surname name
'PatrickLaub'
= f"Hello {name} {surname}"
greeting greeting
'Hello Patrick Laub'
"Patrick" in greeting
True
and
& or
= "Patrick"
name = "Laub"
surname and surname.istitle() name.istitle()
True
= "Dr Patrick Laub"
full_name "Dr ") or full_name.endswith(" PhD") full_name.startswith(
True
The dot is used denote methods, it can’t be used inside a variable name.
= True i.am.an.unfortunate.R.users
NameError: name 'i' is not defined
help
to get more detailshelp(name.istitle)
Help on built-in function istitle:
istitle() method of builtins.str instance
Return True if the string is a title-cased string, False otherwise.
In a title-cased string, upper- and title-case characters may only
follow uncased characters and lowercase characters only cased ones.
print(f"Five squared is {5*5} and five cubed is {5**3}")
print("Five squared is {5*5} and five cubed is {5**3}")
Five squared is 25 and five cubed is 125
Five squared is {5*5} and five cubed is {5**3}
Use f-strings and avoid the older alternatives:
print(f"Hello {name} {surname}")
print("Hello " + name + " " + surname)
print("Hello {} {}".format(name, surname))
print("Hello %s %s" % (name, surname))
Hello Patrick Laub
Hello Patrick Laub
Hello Patrick Laub
Hello Patrick Laub
= 3
digit digit
3
type(digit)
int
= float(digit)
num num
3.0
type(num)
float
= str(num)
num_str num_str
'3.0'
What is the output of:
= 1
x = 1.0
y print(f"{x == y} and {type(x) == type(y)}")
True and False
What would you add before line 3 to get “True and True”?
= 1
x = 1.0
y = float(x) # or y = int(y)
x print(f"{x == y} and {type(x) == type(y)}")
True and True
= ["Coffee", "Cake", "Sleep"]
desires desires
['Coffee', 'Cake', 'Sleep']
len(desires)
3
0] desires[
'Coffee'
-1] desires[
'Sleep'
2] = "Nap"
desires[ desires
['Coffee', 'Cake', 'Nap']
print([0, 1, 2])
desires
[0, 1, 2]
['Coffee', 'Cake', 'Nap']
0:2] desires[
['Coffee', 'Cake']
0:1] desires[
['Coffee']
2] desires[:
['Coffee', 'Cake']
1.0] desires[
TypeError: list indices must be integers or slices, not float
len(desires) / 2] desires[:
TypeError: slice indices must be integers or None or have an __index__ method
len(desires) / 2, len(desires) // 2
(1.5, 1)
len(desires) // 2] desires[:
['Coffee']
= ["Coffee", "Cake", "Sleep"]
desires "Gadget")
desires.append( desires
['Coffee', 'Cake', 'Sleep', 'Gadget']
desires.pop()
'Gadget'
desires
['Coffee', 'Cake', 'Sleep']
desires.sort() desires
['Cake', 'Coffee', 'Sleep']
3] = "Croissant" desires[
IndexError: list assignment index out of range
None
= ["Coffee", "Cake", "Sleep", "Gadget"]
desires = desires.sort()
sorted_list sorted_list
type(sorted_list)
NoneType
is None sorted_list
True
bool(sorted_list)
False
= ["Coffee", "Cake", "Sleep", "Gadget"]
desires = sorted(desires)
sorted_list print(desires)
sorted_list
['Coffee', 'Cake', 'Sleep', 'Gadget']
['Cake', 'Coffee', 'Gadget', 'Sleep']
= ("Sunny", "Cloudy", "Rainy")
weather print(type(weather))
print(len(weather))
print(weather[-1])
<class 'tuple'>
3
Rainy
"Snowy") weather.append(
AttributeError: 'tuple' object has no attribute 'append'
2] = "Snowy" weather[
TypeError: 'tuple' object does not support item assignment
= (2 + 4) * 3
using_brackets_in_math = (1 + 1 == 2) using_brackets_to_simplify
= ("Snowy")
failure_of_atuple type(failure_of_atuple)
str
= ("Snowy",)
happy_solo_tuple type(happy_solo_tuple)
tuple
= ["Snowy"]
cheeky_solo_list type(cheeky_solo_list)
list
= {"Patrick": "+61 1234", "Café": "(02) 5678"}
phone_book "Patrick"] phone_book[
'+61 1234'
"Café"] = "+61400 000 000"
phone_book[ phone_book
{'Patrick': '+61 1234', 'Café': '+61400 000 000'}
phone_book.keys()
dict_keys(['Patrick', 'Café'])
phone_book.values()
dict_values(['+61 1234', '+61400 000 000'])
= {0: 1, 1: 1, 2: 2, 3: 6, 4: 24, 5: 120, 6: 720, 7: 5040}
factorial 4] factorial[
24
= ["dog", "cat", "bird"]
animals "teddy bear")
animals.append(
animals.pop()
animals.pop()"koala")
animals.append("kangaroo")
animals.append(print(f"{len(animals)} and {len(animals[-2])}")
4 and 5
if
and else
= 50 age
if age >= 30:
print("Gosh you're old")
Gosh you're old
if age >= 30:
print("Gosh you're old")
else:
print("You're still young")
Gosh you're old
if age >= 30:
print("Gosh you're old")
else:
print("You're still young")
IndentationError: expected an indented block after 'else' statement on line 3 (2212277638.py, line 4)
Watch out for mixing tabs and spaces!
= 16
age
if age < 18:
= "School things"
friday_evening_schedule if age < 30:
= "Party 🥳🍾"
friday_evening_schedule if age >= 30:
= "Work" friday_evening_schedule
print(friday_evening_schedule)
Party 🥳🍾
elif
= 16
age
if age < 18:
= "School things"
friday_evening_schedule elif age < 30:
= "Party 🥳🍾"
friday_evening_schedule else:
= "Work"
friday_evening_schedule
print(friday_evening_schedule)
School things
for
Loops= ["coffee", "cake", "sleep"]
desires for desire in desires:
print(f"Patrick really wants a {desire}.")
Patrick really wants a coffee.
Patrick really wants a cake.
Patrick really wants a sleep.
for i in range(3):
print(i)
0
1
2
for i in range(3, 6):
print(i)
3
4
5
range(5)
range(0, 5)
type(range(5))
range
list(range(5))
[0, 1, 2, 3, 4]
for
loopsfor i, desire in enumerate(desires):
print(f"Patrick wants a {desire}, it is priority #{i+1}.")
Patrick wants a coffee, it is priority #1.
Patrick wants a cake, it is priority #2.
Patrick wants a sleep, it is priority #3.
= ["coffee", "cake", "nap"]
desires = ["in the morning", "at lunch", "during a boring lecture"]
times
for desire, time in zip(desires, times):
print(f"Patrick enjoys a {desire} {time}.")
Patrick enjoys a coffee in the morning.
Patrick enjoys a cake at lunch.
Patrick enjoys a nap during a boring lecture.
**2 for x in range(10)] [x
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
**2 for x in range(10) if x % 2 == 0] [x
[0, 4, 16, 36, 64]
They can get more complicated:
* y for x in range(4) for y in range(4)] [x
[0, 0, 0, 0, 0, 1, 2, 3, 0, 2, 4, 6, 0, 3, 6, 9]
* y for x in range(4)] for y in range(4)] [[x
[[0, 0, 0, 0], [0, 1, 2, 3], [0, 2, 4, 6], [0, 3, 6, 9]]
but I’d recommend just using for
loops at that point.
Say that we want to simulate (X \,\mid\, X \ge 100) where X \sim \mathrm{Pareto}(1). Assuming we have simulate_pareto
, a function to generate \mathrm{Pareto}(1) variables:
= []
samples while len(samples) < 5:
= simulate_pareto()
x if x >= 100:
samples.append(x)
samples
[125.28600493316272,
186.04974709289712,
154.45723763510398,
101.08310878885993,
2852.8305399214996]
while True:
= input(">> What would you like to do? ")
user_input
if user_input == "order cake":
print("Here's your cake! 🎂")
elif user_input == "order coffee":
print("Here's your coffee! ☕️")
elif user_input == "quit":
break
>> What would you like to do? order cake
Here's your cake! 🎂
>> What would you like to do? order coffee
Here's your coffee! ☕️
>> What would you like to do? order cake
Here's your cake! 🎂
>> What would you like to do? quit
What does this print out?
if 1 / 3 + 1 / 3 + 1 / 3 == 1:
if 2**3 == 6:
print("Math really works!")
else:
print("Math sometimes works..")
else:
print("Math doesn't work")
Math sometimes works..
What does this print out?
= 0
count for i in range(1, 10):
+= i
count if i > 3:
break
print(count)
10
= 0
count for i in range(1, 10):
+= i
count print(f"After i={i} count={count}")
if i > 3:
break
After i=1 count=1
After i=2 count=3
After i=3 count=6
After i=4 count=10
def add_one(x):
return x + 1
def greet_a_student(name):
print(f"Hi {name}, welcome to the AI class!")
10) add_one(
11
"Josephine") greet_a_student(
Hi Josephine, welcome to the AI class!
"Joseph") greet_a_student(
Hi Joseph, welcome to the AI class!
Here, name
is a parameter and the value supplied is an argument.
Assuming we have simulate_standard_normal
, a function to generate \mathrm{Normal}(0, 1) variables:
def simulate_normal(mean=0, std=1):
return mean + std * simulate_standard_normal()
# same as 'simulate_normal(0, 1)' simulate_normal()
0.47143516373249306
1_000) # same as 'simulate_normal(1_000, 1)' simulate_normal(
998.8090243052935
We’ll cover random numbers next week (using numpy
).
=1_000) # same as 'simulate_normal(1_000, 1)' simulate_normal(mean
1001.4327069684261
=1_000) # same as 'simulate_normal(0, 1_000)' simulate_normal(std
-312.6518960917129
10, std=0.001) # same as 'simulate_normal(10, 0.001)' simulate_normal(
9.999279411266635
=10, 1_000) simulate_normal(std
SyntaxError: positional argument follows keyword argument (1723181129.py, line 1)
E.g. to fit a Keras model, we use the .fit
method:
=None, y=None, batch_size=None, epochs=1, verbose='auto',
model.fit(x=None, validation_split=0.0, validation_data=None,
callbacks=True, class_weight=None, sample_weight=None,
shuffle=0, steps_per_epoch=None, validation_steps=None,
initial_epoch=None, validation_freq=1,
validation_batch_size=10, workers=1, use_multiprocessing=False) max_queue_size
Say we want all the defaults except changing use_multiprocessing=True
:
None, None, None, 1, 'auto', None, 0.0, None, True, None,
model.fit(None, 0, None, None, None, 1, 10, 1, True)
but it is much nicer to just have:
=True) model.fit(use_multiprocessing
What does the following print out?
def get_half_of_list(numbers, first=True):
if first:
return numbers[: len(numbers) // 2]
else:
return numbers[len(numbers) // 2 :]
= [1, 2, 3, 4, 5, 6]
nums = get_half_of_list(nums, False)
chunk = get_half_of_list(chunk)
second_chunk print(second_chunk)
[4]
f"nums ~> {nums[:len(nums)//2]} and {nums[len(nums)//2:]}"
'nums ~> [1, 2, 3] and [4, 5, 6]'
f"chunk ~> {chunk[:len(chunk)//2]} and {chunk[len(chunk)//2:]}"
'chunk ~> [4] and [5, 6]'
def limits(numbers):
return min(numbers), max(numbers)
1, 2, 3, 4, 5]) limits([
(1, 5)
type(limits([1, 2, 3, 4, 5]))
tuple
= limits([1, 2, 3, 4, 5])
min_num, max_num print(f"The numbers are between {min_num} and {max_num}.")
The numbers are between 1 and 5.
= limits([1, 2, 3, 4, 5])
_, max_num print(f"The maximum is {max_num}.")
The maximum is 5.
print(f"The maximum is {limits([1, 2, 3, 4, 5])[1]}.")
The maximum is 5.
= limits([1, 2, 3, 4, 5])
lims = lims[0]
smallest_num = lims[1]
largest_num print(f"The numbers are between {smallest_num} and {largest_num}.")
The numbers are between 1 and 5.
= limits([1, 2, 3, 4, 5])
smallest_num, largest_num print(f"The numbers are between {smallest_num} and {largest_num}.")
The numbers are between 1 and 5.
This doesn’t just work for functions with multiple return values:
= (1920, 1080)
RESOLUTION = RESOLUTION
WIDTH, HEIGHT print(f"The resolution is {WIDTH} wide and {HEIGHT} tall.")
The resolution is 1920 wide and 1080 tall.
def is_positive(x):
print("Called is_positive")
return x > 0
def is_negative(x):
print("Called is_negative")
return x < 0
= 10 x
= is_positive(x)
x_is_positive x_is_positive
Called is_positive
True
= is_negative(x)
x_is_negative x_is_negative
Called is_negative
False
= is_positive(x) or is_negative(x)
x_not_zero x_not_zero
Called is_positive
True
import os
import time
0.1) time.sleep(
os.getlogin()
'plaub'
os.getcwd()
'/home/plaub/Dropbox/Lecturing/ACTL3143/DeepLearningForActuaries/Artificial-Intelligence'
from os import getcwd, getlogin
from time import sleep
0.1) sleep(
getlogin()
'plaub'
getcwd()
'/home/plaub/Dropbox/Lecturing/ACTL3143/DeepLearningForActuaries/Artificial-Intelligence'
from time import time
= time()
start_time
= 0
counting for i in range(1_000_000):
+= 1
counting
= time()
end_time
= end_time - start_time
elapsed print(f"Elapsed time: {elapsed} secs")
Elapsed time: 0.11434078216552734 secs
as
import pandas
pandas.DataFrame(
{"x": [1, 2, 3],
"y": [4, 5, 6],
} )
x | y | |
---|---|---|
0 | 1 | 4 |
1 | 2 | 5 |
2 | 3 | 6 |
import pandas as pd
pd.DataFrame(
{"x": [1, 2, 3],
"y": [4, 5, 6],
} )
x | y | |
---|---|---|
0 | 1 | 4 |
1 | 2 | 5 |
2 | 3 | 6 |
Want keras.models.Sequential()
.
import keras
= keras.models.Sequential() model
Alternatives using from
:
from keras import models
= models.Sequential() model
from keras.models import Sequential
= Sequential() model
Example: how to sort strings by their second letter?
= ["Josephine", "Patrick", "Bert"] names
If you try help(sorted)
you’ll find the key
parameter.
for name in names:
print(f"The length of '{name}' is {len(name)}.")
The length of 'Josephine' is 9.
The length of 'Patrick' is 7.
The length of 'Bert' is 4.
sorted(names, key=len)
['Bert', 'Patrick', 'Josephine']
Example: how to sort strings by their second letter?
= ["Josephine", "Patrick", "Bert"] names
If you try help(sorted)
you’ll find the key
parameter.
def second_letter(name):
return name[1]
for name in names:
print(f"The second letter of '{name}' is '{second_letter(name)}'.")
The second letter of 'Josephine' is 'o'.
The second letter of 'Patrick' is 'a'.
The second letter of 'Bert' is 'e'.
sorted(names, key=second_letter)
['Patrick', 'Bert', 'Josephine']
Example: how to sort strings by their second letter?
= ["Josephine", "Patrick", "Bert"] names
If you try help(sorted)
you’ll find the key
parameter.
sorted(names, key=lambda name: name[1])
['Patrick', 'Bert', 'Josephine']
Don’t use lambda
as a variable name! You commonly see lambd
or lambda_
or λ
.
Example, opening a file:
Most basic way is:
= open("haiku1.txt", "r")
f print(f.read())
f.close()
Chaos reigns within.
Reflect, repent, and reboot.
Order shall return.
Instead, use:
with open("haiku2.txt", "r") as f:
print(f.read())
The Web site you seek
Cannot be located, but
Countless more exist.
from watermark import watermark
print(watermark(python=True, packages="keras,matplotlib,numpy,pandas,seaborn,scipy,torch,tensorflow,tf_keras"))
Python implementation: CPython
Python version : 3.11.9
IPython version : 8.24.0
keras : 3.3.3
matplotlib: 3.9.0
numpy : 1.26.4
pandas : 2.2.2
seaborn : 0.13.2
scipy : 1.11.0
torch : 2.3.1
tensorflow: 2.16.1
tf_keras : 2.16.0
If you came from C (i.e. are a joint computer science student), and were super interested in Python’s internals, maybe you’d be interested in this How variables work in Python video.
help
pip install ...
range
type